package solver;

import java.util.HashMap;
import java.util.Iterator;

import tools.*;
import uncertainty.*;

public class VariableMapping {
	
	int var;
	int dim;
	int k;
	
	private class StrucData{
		private Vector<Double> xi;
		private int t;
		private int tp;
	}
	
	private class StrucRecXiT implements Comparable<StrucRecXiT>{

		private int t;
		private Vector<Double> vec;

		public StrucRecXiT(Vector<Double> projection, int t2) {
			vec = projection;
			t = t2;
		}

		@Override
		public int compareTo(StrucRecXiT o) {
			if(t < o.t) return 1;
			else if (t > o.t) return -1;
			else return vec.compareTo(o.vec);
		}
		
	}
		
	private HashMap<StrucRecXiT, Integer> mapQ;
	private HashMap<StrucRecXiT, Integer> mapGamma;
	private HashMap<Integer, StrucData> invmap;
	private int indexC;
	
	public VariableMapping(int dim, int k) {
		indexC = 0;
		var = 1;
		this.dim = dim;
		this.k = k;
		mapQ = new HashMap<VariableMapping.StrucRecXiT, Integer>();
		mapGamma = new HashMap<VariableMapping.StrucRecXiT, Integer>();
	}
	
	public void calculateVariables(UncertaintySet su){
		Iterator<Vector<Double>> it = su.extremePoints();
		
		while(it.hasNext()){
			
			Vector<Double> e = it.next();
			Vector<Double> e1;
		
			for(int m = 0; m < dim; m++){
					e1 = e.getProjection(m - k);
					StrucRecXiT e2 = new StrucRecXiT(e1, m);
					
					if(!mapQ.containsKey(e2)){
						StrucData data = new StrucData();
						data.t = m;
						data.xi = e1;
						data.tp = 1;
						mapQ.put(e2, new Integer(var));
						invmap.put(new Integer(var), data);
						var++;
						data = new StrucData();
						data.t = m;
						data.xi = e1;
						data.tp = 1;
						mapGamma.put(e2, new Integer(var));
						invmap.put(new Integer(var), data);
						var++;				
					}
			}
		}
	}
	
	public int getVariablesGamma(Vector<Double> xi, int t){
		return mapGamma.get(new StrucRecXiT(xi.getProjection(k), t));
	}
	
	public int getVariablesQ(Vector<Double> xi, int t){
		return mapQ.get(new StrucRecXiT(xi.getProjection(k), t));
	}
	
	public int getVariableInd(){
		return indexC;
	}
	
	public int getTimeOfVarible(int index){
		return invmap.get(new Integer(index)).t;
	}
	
	public Vector<Double> getXiOfVariable(int index){
		return invmap.get(new Integer(index)).xi;
	}
	
	public int getTypeOfVarible(int index){
		return invmap.get(new Integer(index)).tp;
	}

	public int getNumVar() {
		return var;
	}
}
